#include "jointstatuswidget.h"
#include <QLabel>
#include <QHBoxLayout>
#include <QDebug>
#include <QLineEdit>

//#include "tcpstatuswidget.h"

mMessage mStatus;
QHash<QString, mEventmsg> mEvent;


JointStatusWidget::JointStatusWidget(const QJsonObject& status, QWidget* parent)
    : QWidget(parent) {
    // 解析 status 部分
    QJsonObject parameters = status["Parameters"].toObject();
    qDebug() << parameters << Qt::endl;

    // 获取 jointPosition 和 jointVelocity
    QJsonObject jointPosition = parameters["jointPosition"].toObject();
    QJsonObject jointVelocity = parameters["jointVelocity"].toObject();

    // 创建状态信息组框
    QGroupBox *statusGroupBox = new QGroupBox("Joint Status Information", this);
    statusGroupBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    QVBoxLayout *statusGroupBoxLayout = new QVBoxLayout(statusGroupBox);

    statusGroupBoxLayout->setContentsMargins(5,5,5,5);


    // 遍历 jointPosition 和 jointVelocity 中的每个关节
    for (auto it = jointPosition.begin(); it != jointPosition.end(); ++it) {
        QString jointName = it.key();  // joint_0, joint_1, ...
        jointNameList.push_back(jointName);
        QString positionValue = it.value().toString();  // 获取位置值
        if(jointName == "uiElement") continue;

        // 从 jointVelocity 中获取对应关节的速度值
        QString velocityValue = jointVelocity[jointName].toString();

        // 调用 createJointControl 函数，传入关节名称、位置值和速度值
        createJointControl(jointName, positionValue, velocityValue, statusGroupBoxLayout);
    }

    // 设置 layout
    QVBoxLayout *mainLayout = new QVBoxLayout(this);

    mainLayout->setContentsMargins(0,0,0,0);

    mainLayout->addWidget(statusGroupBox);

    setLayout(mainLayout);
    //std::this_thread::sleep_for(std::chrono::milliseconds(1000));


    nodeInit();

    // QObject::connect(this, &JointStatusWidget::tcpMessageReceived,
    //                  TcpStatusWidget::instance(), &TcpStatusWidget::tcpStatusCallBack,
    //                  Qt::QueuedConnection);
}

void JointStatusWidget::createJointControl(const QString& jointName, const QString& positionValue, const QString& velocityValue, QVBoxLayout* layout) {
    // 创建一个 QWidget 来显示关节信息
    QWidget *jointWidget = new QWidget(this);
    QHBoxLayout *jointLayout = new QHBoxLayout(jointWidget);
    jointLayout->setContentsMargins(0,0,0,0);



    // 在关节名称控件前添加弹簧
    jointLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));

    // 显示关节名称
    QLabel *jointLabel = new QLabel(jointName  + " :", jointWidget);
    jointLayout->addWidget(jointLabel);

    // // 在关节名称控件后添加弹簧
    // jointLayout->addItem(spring);

    // 创建 QLineEdit 来显示位置
    QLineEdit *positionLineEdit = new QLineEdit(positionValue, jointWidget);
    positionLineEdit->setReadOnly(true);  // 设置为只读
    jointLayout->addWidget(positionLineEdit);

    // // 在位置控件后添加弹簧
    // jointLayout->addItem(spring);

    // 在 QLineEdit 后添加一个 QLabel 来显示单位 "°"
    QLabel *positionUnitLabel = new QLabel("°", jointWidget);  // 这里是单位标签
    jointLayout->addWidget(positionUnitLabel);

    // 在单位标签后添加弹簧
    jointLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));

    // 显示速度标签
    QLabel *velocityLabel = new QLabel("Velocity: ", jointWidget);
    jointLayout->addWidget(velocityLabel);

    // // 在速度标签后添加弹簧
    // jointLayout->addItem(spring);

    // 创建 QLineEdit
    QLineEdit *velocityLineEdit = new QLineEdit(velocityValue, jointWidget);
    velocityLineEdit->setReadOnly(true);  // 设置为只读
    jointLayout->addWidget(velocityLineEdit);

    // // 在速度控件后添加弹簧
    // jointLayout->addItem(spring);

    // 在速度 QLineEdit 后添加一个 QLabel 来显示单位 "°/s"
    QLabel *velocityUnitLabel = new QLabel("°/s", jointWidget);  // 这里是单位标签
    jointLayout->addWidget(velocityUnitLabel);

     // 在单位标签后添加弹簧
    jointLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
    // 存储 QLineEdit 以便后续访问
    jointPositionLineEdits[jointName] = positionLineEdit;
    jointVelocityLineEdits[jointName] = velocityLineEdit;

    // 将 jointWidget 添加到布局中
    layout->addWidget(jointWidget);


}

void JointStatusWidget::updateJointPosition(const QString& jointName, const QString& newPosition) {
    if (jointPositionLineEdits.contains(jointName)) {
        jointPositionLineEdits[jointName]->setText(newPosition);  // 更新位置 QLineEdit 的内容
    } else {
        qDebug() << "Joint name not found: " << jointName;
    }
}

void JointStatusWidget::updateJointVelocity(const QString& jointName, const QString& newVelocity) {
    if (jointVelocityLineEdits.contains(jointName)) {
        jointVelocityLineEdits[jointName]->setText(newVelocity);  // 更新速度 QLineEdit 的内容
    } else {
        qDebug() << "Joint name not found: " << jointName;
    }
}


void JointStatusWidget::nodeInit()
{

    uint32_t domainId = 0; // 或从UI/配置获取
    QString f_deviceID = "ORS_CMOR";
    createAndSubscribeNewNode(domainId,f_deviceID);
    // std::this_thread::sleep_for(std::chrono::milliseconds(1000));

}



void JointStatusWidget::on_msgStatuReceived(const QString &msg)
{
    // 当接收到订阅消息时，在 UI 中显示或记录
    //qDebug() << "JointStatusWidget received message:" << msg;
    // 假设有一个 QTextEdit 控件显示消息，objectName 为 textEditReceived
    //ui->textEditReceived->append(msg);
    //emit tcpMessageReceived();
    processStatuMessage(msg);
}

void JointStatusWidget::on_msgEventReceived(const QString &msg)
{
    // 当接收到订阅消息时，在 UI 中显示或记录
    //qDebug() << "JointEventWidget received message:" << msg;
    // 假设有一个 QTextEdit 控件显示消息，objectName 为 textEditReceived
    //ui->textEditReceived->append(msg);
    //processEventMessage(msg);
    subEventCallBack(msg);
}


void JointStatusWidget::createAndSubscribeNewNode(uint32_t domainId, const QString& deviceID)
{
    // 1. 创建新的DDS节点
    DdsClientWrapper* newClient = new DdsClientWrapper(this);

    // 2. 初始化节点（可以传入不同的domain和topic）
    //uint32_t domainId = 0; // 或从UI/配置获取
   // QString pubName = pubTopic; // 固定话题
   // QString subName = subTopic; // 固定话题


    if(!newClient->initialize(domainId, deviceID)) {
        qWarning() << "Failed to initialize new DDS node";
        delete newClient;
        return;
    }

    // 3. 开始订阅
    if(newClient->startSubscription() == CNP_RESULT::CNP_SUBSCRIBE_SUCCESS) {
        qDebug() << "New DDS node subscribed successfully to deviceID:" << deviceID;

        // 连接信号槽
        connect(newClient, &DdsClientWrapper::msgStatuReceived,
                this, &JointStatusWidget::on_msgStatuReceived);

        connect(newClient, &DdsClientWrapper::msgEventReceived,
                this, &JointStatusWidget::on_msgEventReceived);
        // 保存到列表
        ddsClients_.append(newClient);
    } else {
        qWarning() << "Failed to subscribe new DDS node";
        delete newClient;
    }
}

void JointStatusWidget::processEventMessage(const QString &jsonString) {
    // 将 QString 转换为 QByteArray 进行 JSON 解析
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "解析 JSON 出错:" << parseError.errorString();
        return;
    }
    if (!doc.isObject()) {
        qWarning() << "JSON 数据不是对象格式";
        return;
    }

    QJsonObject jsonObj = doc.object();

    // 获取 device_id 字段
    QString deviceIdStr = jsonObj.value("device_id").toString();

    // 获取 message_id 字段作为 timestamp
    QString timestampStr = jsonObj.value("message_id").toString();

    // 解析 content 对象
    QJsonObject contentObj = jsonObj.value("content").toObject();
    QHash<QString, QString> content;
    for (auto it = contentObj.begin(); it != contentObj.end(); ++it) {
        content.insert(it.key(), it.value().toString());
    }

    // 构造 mMessage 对象
    mEventmsg msg;
    msg.device_id = deviceIdStr;
    msg.timestamp = timestampStr;
    msg.mContent = content;

    // 将消息保存到全局变量 mStatus 中，以 deviceIdStr 作为键
    mEvent.insert(deviceIdStr, msg);
}

void JointStatusWidget::subEventCallBack(const QString &jsonString)
{
    // 解析原始 JSON
    //QString rawJson = QString::fromStdString(msg.content());
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError);

    QString key = "unknown", value = "";

    {
        QMutexLocker locker(&mJointStatuMutex);
        if (parseError.error == QJsonParseError::NoError && doc.isObject()) {
            QJsonObject obj = doc.object();
            if      (obj.contains("event"))   { key = "event";   value = obj["event"].toString(); }
            else if (obj.contains("warning")) { key = "warning"; value = obj["warning"].toString(); }
            else if (obj.contains("error"))   { key = "error";   value = obj["error"].toString(); }
            else if (obj.contains("fatal"))   { key = "fatal";   value = obj["fatal"].toString(); }
            else if (obj.contains("command")) { key = "command"; value = obj["command"].toString(); }
            else {
                qWarning() << "收到未知字段的 JSON：" << jsonString;
            }
            value = "(CMOR) "+value;
        } else {
            qWarning() << "JSON 解析失败：" << parseError.errorString();
        }
    }

    qDebug() << "解析到：" << key << "=" << value;
    // 用 QStringList 传递
    emit upSubEvent(QStringList{key, value});
}

void JointStatusWidget::processStatuMessage(const QString &msg) {
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(msg.toUtf8(), &parseError);

    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "JSON 解析错误:" << parseError.errorString();
        return;
    }

    QJsonObject root = doc.object();

    // 获取 device_id 字段
    QString deviceIdStr = root.value("device_id").toString();

    // 获取 message_id 字段作为 timestamp
    QString timestampStr = root.value("message_id").toString();

    // 解析 content 对象，存入 QHash<QString, std::vector<double>>
    // 提取 endPose 数组
    std::vector<double> endPoseVec;
    if (root.contains("endPose") && root["endPose"].isArray()) {
        QJsonArray jsonArray = root["endPose"].toArray();

        for (const auto &value : jsonArray) {
            endPoseVec.push_back(value.toDouble());
        }
        mStatus.mContent.insert("endPose", endPoseVec);
    }

    // 提取 jointAngle 数组
     std::vector<double> jointAngleVec;
    if (root.contains("jointAngle") && root["jointAngle"].isArray()) {
        QJsonArray jsonArray = root["jointAngle"].toArray();

        for (const auto &value : jsonArray) {
            jointAngleVec.push_back(value.toDouble());
        }
        mStatus.mContent.insert("jointAngle", jointAngleVec);
    }

    // 提取 jointVelocity 数组
    std::vector<double> jointVelocityVec;
    if (root.contains("jointVelocity") && root["jointVelocity"].isArray()) {
        QJsonArray jsonArray = root["jointVelocity"].toArray();

        for (const auto &value : jsonArray) {
            jointVelocityVec.push_back(value.toDouble());
        }
        mStatus.mContent.insert("jointVelocity", jointVelocityVec);
    }

    UpdateUI();//更新界面内容
}

void JointStatusWidget::UpdateUI()
{
    if(jointNameList.size()<1)
        return;
    std::vector<double> positionValue = mStatus.mContent["jointAngle"];
    std::vector<double> veloValue = mStatus.mContent["jointVelocity"];

    if(positionValue.size()<1)
    {
        std::cout<<"positionValue.size()= "<<positionValue.size()<<std::endl;
        std::cout<<"veloValue.size()= "<<veloValue.size()<<std::endl;
        return;
    }

    if(veloValue.size()<1)
    {
        std::cout<<"veloValue.size()=0;"<<std::endl;
        return;
    }
    // std::cout<<"positionValue.size()= "<<positionValue.size()<<std::endl;
    // std::cout<<"veloValue.size()= "<<veloValue.size()<<std::endl;
    // std::cout<<"jointNameList.size()= "<<jointNameList.size()<<std::endl;

    for(int i=0;i<veloValue.size();i++)
    {
        updateJointPosition(jointNameList[i],QString::number(positionValue[i], 'f', 3));
        updateJointVelocity(jointNameList[i],QString::number(veloValue[i], 'f', 3));
    }
}


